﻿using Microsoft.Phone.Controls.Maps;
using Microsoft.Phone.Controls.Maps.Platform;
using System;
using System.Collections.Generic;
using System.Device.Location;
using System.Windows;
using System.Windows.Media;
using System.Windows.Shapes;
using WP7_Adresboek.GeocodeService;
using WP7_Adresboek.RouteService;

namespace WP7_Adresboek
{
    public partial class Map
    {
        private readonly Controller _control;
        private readonly GeoCoordinateWatcher _watcher;
        private static Pushpin _currentLocation;
        private List<Microsoft.Phone.Controls.Maps.Platform.Location> _navigationList;
        internal GeocodeService.GeocodeResult[] geocodeResults;

        public Map()
        {
            _control = App.Control;
            InitializeComponent();
            _watcher = new GeoCoordinateWatcher(GeoPositionAccuracy.High)
            {
                MovementThreshold = 10
            };
            _watcher.PositionChanged += GpsPositionChanged;
            _watcher.StatusChanged += GpsStatuChanged;
            _watcher.Start();
            _navigationList = new List<Microsoft.Phone.Controls.Maps.Platform.Location>();
            LoadContactLocations();
        }

        public void LoadContactLocations()
        {
            foreach(HistoryTable contact in _control.LoadHistoryList())
            {
                Pushpin location = new Pushpin();
                location.Tag = contact;
                location.Content = contact.Id;
                location.Location = new GeoCoordinate(contact.Latitude, contact.Longitude);
                location.MouseLeftButtonUp += AddLocation;
                ContactMap.Children.Add(location);
            }
        }

        private void AddLocation(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            Pushpin loc = ((FrameworkElement)sender) as Pushpin;
            if (loc != null)
            {
                HistoryTable location = loc.Tag as HistoryTable;
                _navigationList.Add(new GeoCoordinate(location.Latitude, location.Longitude));
                MessageBox.Show("Locatie " + loc.Content + " toegevoegd aan de route.");
            }
        }

        public static Microsoft.Phone.Controls.Maps.Platform.Location RequestCurrentLocation()
        {
            if(_currentLocation != null)
                return _currentLocation.Location;
            return new GeoCoordinate(0.0, 0.0);
        }

        private static void GpsStatuChanged(object sender, GeoPositionStatusChangedEventArgs gpsStatus)
        {
            switch(gpsStatus.Status)
            {
                case GeoPositionStatus.Disabled:
                    MessageBox.Show("Zet a.u.b de GPS aan");
                    break;
                case GeoPositionStatus.NoData:
                    MessageBox.Show("Er kan nu geen GPS-signaal worden gevonden");
                    break;
            }
        }

        private void GpsPositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e)
        {
            ZoomOnCurrentLocation(e.Position.Location);
        }

        private void ZoomOnCurrentLocation(GeoCoordinate location)
        {
            ContactMap.Center = location;
            ContactMap.ZoomLevel = 13;
            if (_currentLocation != null) 
                ContactMap.Children.Remove(_currentLocation);
            _currentLocation = new Pushpin
            {
                Template = null,
                Content = new Ellipse
                {
                    Fill = new SolidColorBrush(Colors.Red),
                    StrokeThickness = 0,
                    Opacity = .8,
                    Height = 15,
                    Width = 15
                },
                Location = location
            };
            ContactMap.Children.Add(_currentLocation);
        }

        private void CalculateRoute(object sender, RoutedEventArgs e)
        {
            WP7_Adresboek.RouteService.Location[] routeList = new WP7_Adresboek.RouteService.Location[_navigationList.Count];
            if (_navigationList.Count <= 1)
                MessageBox.Show("Kies a.u.b. 2 of meer locaties voor de route.");
            else
            {
                for (int i = 0; i < _navigationList.Count; i++)
                {
                    routeList[i] = new WP7_Adresboek.RouteService.Location();
                    routeList[i].Latitude = _navigationList[i].Latitude;
                    routeList[i].Longitude = _navigationList[i].Longitude;
                }
                geocodeResults = new GeocodeService.GeocodeResult[routeList.Length];
                GeocodeResultToWaypoint(routeList);
                _navigationList.Clear();
            }
        }

        #region RouteService Code
        private RouteService.Waypoint GeocodeResultToWaypoint(WP7_Adresboek.RouteService.Location[] result)
        {
            // Create the service variable and set the callback method using the CalculateRouteCompleted property.
            RouteService.RouteServiceClient routeService = new RouteService.RouteServiceClient("BasicHttpBinding_IRouteService");
            routeService.CalculateRouteCompleted += new EventHandler<RouteService.CalculateRouteCompletedEventArgs>(routeService_CalculateRouteCompleted);
            // Set the token.
            RouteService.RouteRequest routeRequest = new RouteService.RouteRequest();
            routeRequest.Credentials = new WP7_Adresboek.RouteService.Credentials();
            routeRequest.Credentials.ApplicationId = ((ApplicationIdCredentialsProvider)ContactMap.CredentialsProvider).ApplicationId;
            // Return the route points so the route can be drawn.
            routeRequest.Options = new RouteService.RouteOptions();
            routeRequest.Options.RoutePathType = RouteService.RoutePathType.Points;
            routeRequest.Waypoints = new System.Collections.ObjectModel.ObservableCollection<RouteService.Waypoint>();
            routeRequest.Options.Mode = TravelMode.Driving;
            int i = 0;
            foreach (WP7_Adresboek.RouteService.Location l in result)
            {
                Waypoint point = new RouteService.Waypoint();
                point.Location = l;
                routeRequest.Waypoints.Add(point);
                geocodeResults[i] = new GeocodeResult();
                GeocodeService.GeocodeLocation loc = new GeocodeService.GeocodeLocation();
                loc.Latitude = l.Latitude;
                loc.Longitude = l.Longitude;
                geocodeResults[i].Locations = new System.Collections.ObjectModel.ObservableCollection<GeocodeService.GeocodeLocation>();
                geocodeResults[i].Locations.Add(loc);
                i++;
            }
            routeService.CalculateRouteAsync(routeRequest);
            return null;
        }

        private void routeService_CalculateRouteCompleted(object sender, RouteService.CalculateRouteCompletedEventArgs e)
        {
            if ((e.Result.ResponseSummary.StatusCode == RouteService.ResponseStatusCode.Success) & (e.Result.Result.Legs.Count != 0))
            {
                ContactMap.Children.RemoveAt(ContactMap.Children.Count - 1);
                Color routeColor = Colors.Blue;
                SolidColorBrush routeBrush = new SolidColorBrush(routeColor);
                MapPolyline routeLine = new MapPolyline();
                routeLine.Locations = new LocationCollection();
                routeLine.Stroke = routeBrush;
                routeLine.Opacity = 0.65;
                routeLine.StrokeThickness = 5.0;
                foreach (WP7_Adresboek.RouteService.Location p in e.Result.Result.RoutePath.Points)
                {
                    routeLine.Locations.Add(new GeoCoordinate(p.Latitude, p.Longitude));
                }
                MapLayer myRouteLayer = new MapLayer();
                ContactMap.Children.Add(myRouteLayer);
                myRouteLayer.Children.Add(routeLine);
                LocationRect rect = new LocationRect(Microsoft.Phone.Controls.Maps.LocationRect.CreateLocationRect(routeLine.Locations[0], routeLine.Locations[routeLine.Locations.Count - 1]));
                ContactMap.SetView(rect);
            }
        }
        #endregion
    }
}